package com.bulk.demo.insert.service.impl;

import com.bulk.demo.insert.entity.Student;
import com.bulk.demo.insert.mapper.StudentMapper;
import com.bulk.demo.insert.service.IThreadCallbackService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * //  TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
 *
 * @author 散装java
 * @since 2022/6/25
 */
@Service
@Primary
@Slf4j
public class ThreadCallbackServiceImpl implements IThreadCallbackService {
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private SqlSessionTemplate sqlSessionTemplate;
    @Resource
    private ThreadPoolTaskExecutor asyncServiceExecutor;

    public SqlSession getSqlSession() {
        SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
        return sqlSessionFactory.openSession();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void threadCallback1() {
        Student student = new Student();
        student.setName("散装java");
        studentMapper.insert(student);
        new Thread(() -> {
            Student student1 = new Student();
            student1.setName("吴sir");
            studentMapper.insert(student1);
            throw new RuntimeException("手动异常");
        }).start();
    }

    @SneakyThrows
    @Override
    public void threadCallback2() {
        SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession();
        Connection connection = sqlSession.getConnection();
        connection.setAutoCommit(false);
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        try {
            Student student = new Student();
            student.setName("散装java");
            mapper.insert(student);
            List<CompletableFuture<Void>> list = new ArrayList<>();

            for (int i = 0; i < 10; i++) {
                AtomicInteger integer = new AtomicInteger(i);
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    Student student1 = new Student();
                    student1.setName("散装java" + integer.get());
                    mapper.insert(student1);
                    if (integer.get() == 3)
                        throw new RuntimeException("手动异常");
                }, asyncServiceExecutor);
                list.add(future);
            }
            CompletableFuture[] arr = list.toArray(new CompletableFuture[0]);
            CompletableFuture<Void> future = CompletableFuture.allOf(arr);
            future.exceptionally((e) -> {
                log.error("线程{}=捕获到异常", Thread.currentThread().getName());
                e.printStackTrace();
                try {
                    connection.rollback();
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
                return null;
            });
            future.get();
            log.info("======执行完毕");
            connection.commit();
        } catch (Exception e) {
            log.error("捕获到错误 ===> {}", e.getMessage());
        } finally {
            connection.close();
        }

    }
}
